package com.tool.cn.util;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Properties;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import com.tool.cn.model.SshModel;

/**
 * 
 * @author wangzonghui
 * @date 2022年1月19日 下午3:44:15 
 * @Description ssh工具类 推荐使用SshSshdUtil 工具类
 */
@Deprecated
public class SshUtil {
	
	private static final Logger log = LoggerFactory.getLogger(SshUtil.class);
	
    public static void main(String[] args) throws Exception {
		String host = "172.16.34.160";
		int port = 22;
		String user = "用户名";
		String password = "密码";
    	SshUtil sshUtil = new SshUtil(host, user,password, port);
    	
    	sshUtil.putFile("文件","上传地址");
        
        String cmd="ls /root/wang/";
        int result=sshUtil.runCommand(cmd);
        System.out.println("返回结果:"+result);
        
    }
	
    
	/**
	 * 说明
	 * 1、不支持免密方式登录    由于jsch版本长久未升级，无法支持最新ssh加密，只能使用密码登录
	 * 2、上传文件有可能session连接失败    因为对方服务器配置sshd参数较小，文件：/etc/ssh/sshd_config  属性：MaxSessions 建议20个
	 * 
	 * 基于jsch方式过于老旧，建议使用新库sshd-core、sshd-sft、sshd-common、sshd-scp
	 */
    
    
	private String host;
	private String user;
	private String password;
	private int port;
	private Session session;

	/**
	 * 创建一个连接
	 * 
	 * @param host     地址
	 * @param user     用户名
	 * @param password 密码
	 * @param port     ssh2端口
	 */
	public SshUtil(String host, String user, String password, int port) {
		this.host = host;
		this.user = user;
		this.password = password;
		this.port = port;
	}
	
	
	/**
	 * 登录测试
	 * @return
	 */
	public boolean loginTest() {
		try {
			initialSession();
		} catch (Exception e) {
			log.error("SSH Login Error"+e.toString(),e);
			return false;
		}
		
		try {
			close();
		} catch (Exception e) {
			log.error("Close SSH Error",e);
		}
		return true;
	}

	private void initialSession() throws Exception {
		if (session == null||!session.isConnected()) {
			JSch jsch = new JSch();
			session = jsch.getSession(user, host, port);
			
			Properties sessionConfig = new Properties(); 
            //SSH 公钥检查机制 no、ask、yes 
            sessionConfig.put("StrictHostKeyChecking", "no"); 
            
			session.setPassword(password);
			session.setTimeout(10000);
			session.connect();
		}
	}

	/**
	 * 关闭连接
	 * 
	 * @throws Exception
	 */
	public void close()  {
		if (session != null && session.isConnected()) {
			session.disconnect();
			session = null;
		}
	}
	
	/**
	 * 目录验证
	 * @param path
	 * @return
	 */
	public boolean checkPath(String path) {
		Channel channel=null;
		try {
			this.initialSession();
			channel = session.openChannel("sftp");
			channel.connect();
			ChannelSftp channelSftp = (ChannelSftp) channel;
			channelSftp.cd(path);
			
			return true;
		} catch (Exception e) {
			log.error(e.toString(), e);
			return false;
		}finally {
			if (channel!=null) {
				channel.disconnect();
			}
		}
	}

	/**
	 * 上传文件
	 * 
	 * @param localFile  本地文件名，若为空或是*，表示目前下全部文件
	 * @param remotePath 远程路径，若为空，表示当前路径，若服务器上无此目录，则会自动创建
	 * @throws Exception
	 */
	public boolean putFile( String localFile, String remotePath) {
		Channel channel;
		try {
			this.initialSession();
			channel = session.openChannel("sftp");
			channel.connect();
			ChannelSftp channelSftp = (ChannelSftp) channel;
			String remoteFile = null;
			if (remotePath != null && remotePath.trim().length() > 0) {
				
				if(remotePath.contains("\\")) {    //window盘符转Linux
					remotePath=remotePath.replaceAll("\\\\", "/");
				}
				
				if(channelSftp.ls(remotePath)==null) {
					channelSftp.mkdir(remotePath);
				}
				
				remoteFile = remotePath + "/.";
			} else {
				remoteFile = ".";
			}
			
			channelSftp.put(localFile, remoteFile);
			
		} catch (Exception e) {
			log.error("Host:"+host+" User"+user+" Put File:"+localFile+" Error "+e.toString(), e);
			return false;
		}

		channel.disconnect();
		return true;
	}

	/**
	 * 下载文件
	 * 
	 * @param localPath  本地路径，若为空，表示当前路径
	 * @param localFile  本地文件名，若为空或是*，表示目前下全部文件
	 * @param remotePath 远程路径，若为空，表示当前路径，若服务器上无此目录，则会自动创建
	 * @throws Exception
	 */
	public boolean getFile( String localFile, String remoteFile) {
		Channel channel=null;
		try {
			this.initialSession();
			channel = session.openChannel("sftp");
			channel.connect();
			ChannelSftp channelSftp = (ChannelSftp) channel;

			if(channelSftp.ls(remoteFile)==null) {
				log.error("Sftp Path:{} No Exits",remoteFile);
				return false;
			}
			
			channelSftp.get(remoteFile, localFile);
			
		} catch (Exception e) {
			log.error("Host:"+host+" User"+user+"Get File:"+remoteFile+" Error: "+e.toString(), e);
			return false;
		}finally {
			if (channel!=null) {
				channel.disconnect();
			}
		}

		return true;
	}
	
	/**
	 * 执行远程命令 
	 * @param command 执行的命令
	 * @return 0成功 1异常
	 * @throws Exception
	 */
	public int runCommand(String command)  {

		try {
			this.initialSession();
			int time = 0;
			String s = "";
			boolean run = false;

			ChannelExec channel = (ChannelExec) session.openChannel("exec");
			channel.setCommand(command);
			channel.setInputStream(null);
			channel.setErrStream(null);
			InputStream err = channel.getErrStream();
			InputStream in = channel.getInputStream();
			channel.connect();
			BufferedReader inReader = new BufferedReader(new InputStreamReader(in, "UTF-8"));
			BufferedReader errReader = new BufferedReader(new InputStreamReader(err, "UTF-8"));

			StringBuffer sb = new StringBuffer();
			sb.append("error: ");
			while (true) {
				s = errReader.readLine();
				if (s != null) {
					sb.append(s).append("\n");
				} else {
					run = true;
					break;
				}
			}
			
			sb.append("info: ");
			while (true) {
				s = inReader.readLine();
				if (s != null) {
					sb.append(s).append("\n");
				} else {
					run = true;
					break;
				}
			}

			while (true) {
				if (channel.isClosed() || run) {
					break;
				}
				try {
					Thread.sleep(100);
				} catch (Exception ee) {
				}
				if (time > 180) {

					break;
				}
				time++;
			}

			int status=channel.getExitStatus();
			inReader.close();
			errReader.close();
			channel.disconnect();
			
			String result=sb.toString();
			if(status>0) {
				log.info("{}  host:{} user:{} Run Is code:{} Error :{}",command,host,user,status,result);
			}
			return status;
		} catch (Exception e) {
			log.error("Host:"+host+" User"+user+" Run Command "+command+" Error:"+e.toString(),e);
			return 1;
		}
	}

	/**
	 * 执行远程命令 
	 * @param command 执行的命令
	 * @return 0成功 其他 异常
	 * @throws Exception
	 */
	public SshModel run(String command)  {

		SshModel sshModel=new SshModel();
		try {
			this.initialSession();
			int time = 0;
			String s = "";
			boolean run = false;

			ChannelExec channel = (ChannelExec) session.openChannel("exec");
			channel.setCommand(command);
			channel.setInputStream(null);
			channel.setErrStream(null);
			InputStream err = channel.getErrStream();
			InputStream in = channel.getInputStream();
			channel.connect();
			BufferedReader inReader = new BufferedReader(new InputStreamReader(in, "UTF-8"));
			BufferedReader errReader = new BufferedReader(new InputStreamReader(err, "UTF-8"));

			StringBuffer sb = new StringBuffer();
			while (true) {
				s = errReader.readLine();
				if (s != null) {
					if(s.length()>0) {
						sb.append(s).append("\n");
					}
					
				} else {
					run = true;
					break;
				}
			}
			sshModel.setError(sb.toString());
			
			int num=0;
			sb = new StringBuffer();
			while (true) {
				s = inReader.readLine();
				if (s != null) {
					if(s.length()>0) {
						if(num!=0) {
							sb.append("|");
						}
						sb.append(s);
						num++;
					}
				} else {
					run = true;
					break;
				}
			}
			sshModel.setInfo(sb.toString());
			
			while (true) {
				if (channel.isClosed() || run) {
					break;
				}
				try {
					Thread.sleep(100);
				} catch (Exception ee) {
				}
				if (time > 180) {

					break;
				}
				time++;
			}

			int status=channel.getExitStatus();
			inReader.close();
			errReader.close();
			channel.disconnect();
			
			sshModel.setCode(status);
		} catch (Exception e) {
			log.error("Host:"+host+" User"+user+" Run Command "+command+" Error:"+e.toString(),e);
			sshModel.setCode(1);
		}
		return sshModel;
	}
 
}